#include "Acceptor.h"
#include <unistd.h>
#include "InetAddress.h"
#include <iostream>
using std::cout; using std::endl;

using std::shared_ptr;

Acceptor::Acceptor(string ip, int port, Epoll &epoll)
:listenSock_()
,addr_(ip, port)
,conn_(listenSock_.fd(), addr_, epoll)
{
	addr_.printAddr();
    bindlisten();
	conn_.socktype_ = esock_listen;
    shared_ptr<Channel> pchannel(new Channel());
    conn_.epoll_.epollAdd(listenSock_.fd(), &conn_, pchannel);
}

void Acceptor::bindlisten()
{
    setReuseAddr(true);
    bind();
    listen();
}

void Acceptor::setAcceptorCb(std::function<void()> cb)
{
    conn_.epoll_.channels_[listenSock_.fd()]->onMessCb_ = cb;
}

void Acceptor::setReuseAddr(bool flag)
{
    int on = (flag ? 1 : 0);
    if (::setsockopt(listenSock_.fd(), SOL_SOCKET, SO_REUSEPORT, &on, sizeof(int)))
    {
        perror("setsockopt reuseaddr err");
        ::close(listenSock_.fd());
        exit(EXIT_FAILURE);
    }
}

void Acceptor::bind()
{
    sockaddr_in *addr = addr_.getAddr();
    if (-1 == ::bind(listenSock_.fd(), 
                    (sockaddr *)addr,
                    sizeof(sockaddr_in)))
    {
        perror("bind err");
        ::close(listenSock_.fd());
        exit(EXIT_FAILURE);
    }
}

void Acceptor::listen()
{
    if (-1 == ::listen(listenSock_.fd(), 0))
    {
        perror("listen err");
        ::close(listenSock_.fd());
        exit(EXIT_FAILURE);
    }
}

int Acceptor::accept()
{
    int fd = ::accept(listenSock_.fd(), NULL, NULL);
	if (fd < 0)
	{
		return 0;
	}

	return fd;
}
